package com.mchat.friend.dao;

import com.mchat.friend.domain.po.FriendRequest;
import io.r2dbc.spi.Result;
import io.r2dbc.spi.Row;
import io.r2dbc.spi.RowMetadata;
import lombok.RequiredArgsConstructor;
import org.reactivestreams.Publisher;
import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;
import java.util.function.BiFunction;

@RequiredArgsConstructor
@Component
public class FriendRequestDAO {
    private final DatabaseClient databaseClient;
    private  final BiFunction<Row, RowMetadata, FriendRequest> MAP_FUNCTION = (row, rowMetadata) -> {
        FriendRequest friendRequest = new FriendRequest();
        friendRequest.setId(row.get("id", Long.class));
        friendRequest.setSendId(row.get("send_id", Long.class));
        friendRequest.setReceiverId(row.get("receiver_id", Long.class));
        friendRequest.setMsg(row.get("msg", String.class));
        friendRequest.setStatus(row.get("status",Integer.class));
        friendRequest.setCreateTime(row.get("create_time", LocalDateTime.class));
        friendRequest.setUserGroup(row.get("user_group", String.class));
        friendRequest.setRemarkName(row.get("remark_name", String.class));
        friendRequest.setUpdateTime(row.get("update_time",LocalDateTime.class));
        return friendRequest;
    };
    public Mono<FriendRequest> save(FriendRequest friendRequest){
        //对于重复的申请只更新时间
        String sql= """
                INSERT INTO tb_friend_apply ( send_id,receiver_id,msg,status,create_time,user_group,remark_name)
                VALUES($1,$2,$3,$4,current_timestamp,$5,$6)
                ON CONFLICT (send_id,receiver_id) where status=0
                DO UPDATE SET
                create_time=current_timestamp
                returning * ;
                """;

        return databaseClient.inConnection(connection -> {
            Publisher<? extends Result> execute = connection.createStatement(sql)
                    .bind(0, friendRequest.getSendId())
                    .bind(1, friendRequest.getReceiverId())
                    .bind(2, friendRequest.getMsg())
                    .bind(3, friendRequest.getStatus())
                    .bind(4, friendRequest.getUserGroup())
                    .bind(5, friendRequest.getRemarkName())
                    .execute();
            return Mono.from(execute).flatMap(result -> Mono.from(result.map(MAP_FUNCTION)));
        });

    }
    public Mono<Long> update(long id,int status){
        String sql="update tb_friend_apply set  status = $1 ,update_time =current_timestamp where id =$2";
        return databaseClient.inConnection(connection -> {
            Publisher<? extends Result> execute = connection.createStatement(sql)
                    .bind(0, status)
                    .bind(1, id)
                    .execute();
            return Mono.from(execute).flatMap(result -> Mono.from(result.getRowsUpdated()));
        });
    }
    public Mono<FriendRequest> get(long id){
        return databaseClient.sql("select * from tb_friend_apply where id=$1")
                .bind(0,id)
                .map(MAP_FUNCTION).one();
    }

    public Flux<FriendRequest>getApply(long id){

        String sql= """
                select * from tb_friend_apply where (send_id=$1 and status !=0 ) or (receiver_id=$1 and status=0)
                """;
       return databaseClient.inConnectionMany(connection -> {
           Publisher<? extends Result> execute = connection.createStatement(sql).bind(0, id).fetchSize(50).execute();
           return Flux.from(execute).concatMap(result -> Flux.from(result.map(MAP_FUNCTION)));
       });
    }

}
